package cn.itcast.zt.controller;

import cn.itcast.zt.domain.User;
import cn.itcast.zt.repository.UserRepository;
import cn.itcast.zt.util.CheckUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.validation.Valid;

/**
 * created by zhangtian on 2018/7/8
 */
@RestController
@RequestMapping(value = "user")
public class UserController {

    // 官方推荐使用构造函数注入
    private final UserRepository userRepository ;

    public UserController(UserRepository userRepository){
        this.userRepository = userRepository ;
    }

    /**
     * 以数组形式一次性返回数据
     * @return
     */
    @GetMapping(value = "/")
    public Flux<User> getAll(){
        return userRepository.findAll();
    }

    /**
     * 以SSE形式  逐条返回数据
     * 新的方式  通过SSE逐条获取后台数据
     * @return
     */
    @GetMapping(value = "stream/all", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<User> streamGetAll(){
        return userRepository.findAll();
    }

    /**
     * 新增数据
     * @param user
     * @return
     */
    @PostMapping(value = "/")
    public Mono<User> createUser(@Valid @RequestBody User user) {
        // spring data  jpa  新增修改都是save方法，有id是修改，id为空是新增
        // 根据实际情况是否置空id
        user.setId(null);
        CheckUtil.checkName(user.getName()) ;
        return this.userRepository.save(user) ;
    }

    @DeleteMapping(value = "{id}")
    public Mono<ResponseEntity<Void>> deleteUser(@PathVariable(value = "id") String id) {
        // deleteById 没有返回值，不能判断数据是否存在
        // this.userRepository.deleteById(id) ;
        // 当你要操作数据，并返回一个Mono这个时候使用flatMap
        // 如果不操作数据，只是对数据做一个转换使用map
        return this.userRepository.findById(id)
                .flatMap(user -> this.userRepository.delete(user)
                        .then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK))))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * 修改数据
     * 存在返回200和修改后的数据，不存在的时候返回404
     * @param id
     * @param user
     * @return
     */
    @PutMapping(value = "{id}")
    public Mono<ResponseEntity<User>> updateUser(@PathVariable(value = "id") String id, @Valid @RequestBody User user) {
        return this.userRepository.findById(id)
                // flatMap操作数据
                .flatMap(u -> {
                    u.setAge(user.getAge());
                    u.setName(user.getName());
                    return this.userRepository.save(u) ;
                })
                // map转换数据
                .map(u->new ResponseEntity<User>(u, HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * 根据ID查找用户
     * 存在返回用户信息，不存在返回404
     * @param id
     * @return
     */
    @GetMapping(value = "{id}")
    public Mono<ResponseEntity<User>> getUserById(@PathVariable(value = "id") String id){
        return this.userRepository.findById(id)
                .map(u->new ResponseEntity<User>(u, HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * 根据年龄查找用户
     * @param start
     * @param end
     * @return
     */
    @GetMapping(value = "age/{start}/{end}")
    public Flux<User> findByAge(@PathVariable(value = "start") int start, @PathVariable(value = "end") int end){
        return this.userRepository.findByAgeBetween(start, end );
    }

    /**
     * 根据年龄查找用户
     * SSE形式返回
     * @param start
     * @param end
     * @return
     */
    @GetMapping(value = "stream/age/{start}/{end}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<User> streamFindByAge(@PathVariable(value = "start") int start, @PathVariable(value = "end") int end){
        return this.userRepository.findByAgeBetween(start, end );
    }

    /**
     * 得到年龄20-30用户
     * @return
     */
    @GetMapping(value = "old")
    public Flux<User> findOldUser(){
        return this.userRepository.oldUser();
    }

    /**
     * 得到年龄20-30用户
     * SSE形式返回
     * @return
     */
    @GetMapping(value = "streamOld", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<User> streamFindOldUser(){
        return this.userRepository.oldUser();
    }
}
